//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <core.h>
#include "exception.h"
#include "dodivz.h"

bool  DoDivZ(InterruptContext *pContext)
{
    insDiv * pInsDiv = (insDiv *)pContext->cp0_epc;

    if (0x03 == pInsDiv->div)  {
        if (0x11 == pInsDiv->fmt) {
            dFloatPoint dividend;
            char pinf[]={'\x00','\x00','\x00','\x00',
                         '\x00','\x00','\x00','\x40',};
            char ninf[]={'\x00','\x00','\x00','\x00',
                         '\x00','\x00','\x00','\xc0',};
#if defined(_EVC)
            ASM(".set  noreorder;");
            switch (pInsDiv->fs) {
                case 0:{
                    ASM("sdc1   $f0,0(%0);"
                        "lw     t0,4(%0);"
                        "andi   t0,t0,0x80;"
                        "beq    t0,zero,l0;"
                        "ldc1   $f0,0(%2);"
                        "ldc1   $f0,0(%1);"
                        "l0: "
                        , &dividend, &ninf, &pinf);
                    break;
                }
                case 2:{
                    ASM("sdc1   $f2,0(%0);"
                        "lb     t0,7(%0);"
                        "andi   t0,t0,0x80;"
                        "beq    t0,zero,l2;"
                        "ldc1   $f2,0(%2);"
                        "ldc1   $f2,0(%1);"
                        "l2: "
                        , &dividend, &ninf, &pinf);
                    break;
                }
                case 4:{
                    ASM("sdc1   $f4,0(%0);"
                        "lb     t0,7(%0);"
                        "andi   t0,t0,0x80;"
                        "beq    t0,zero,l4;"
                        "ldc1   $f4,0(%2);"
                        "ldc1   $f4,0(%1);"
                        "l4: "
                        , &dividend, &ninf, &pinf);
                    break;
                }
                case 6:{
                    ASM("sdc1   $f6,0(%0);"
                        "lb     t0,7(%0);"
                        "andi   t0,t0,0x80;"
                        "beq    t0,zero,l6;"
                        "ldc1   $f6,0(%2);"
                        "ldc1   $f6,0(%1);"
                        "l6: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 8:{
                    ASM("sdc1   $f8,0(%0);"
                        "lb     t0,7(%0);"
                        "andi   t0,t0,0x80;"
                        "beq    t0,zero,l8;"
                        "ldc1   $f8,0(%2);"
                        "ldc1   $f8,0(%1);"
                        "l8: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 10:{
                    ASM("sdc1  $f10,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l10;"
                        "ldc1  $f10,0(%2);"
                        "ldc1  $f10,0(%1);"
                        "l10: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 12:{
                    ASM("sdc1  $f12,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l12;"
                        "ldc1  $f12,0(%2);"
                        "ldc1  $f12,0(%1);"
                        "l12: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 14:{
                    ASM("sdc1  $f14,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l14;"
                        "ldc1  $f14,0(%2);"
                        "ldc1  $f14,0(%1);"
                        "l14: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 16:{
                    ASM("sdc1  $f16,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l16;"
                        "ldc1  $f16,0(%2);"
                        "ldc1  $f16,0(%1);"
                        "l16: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 18:{
                    ASM("sdc1  $f18,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l18;"
                        "ldc1  $f18,0(%2);"
                        "ldc1  $f18,0(%1);"
                        "l18: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 20:{
                    ASM("sdc1  $f20,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l20;"
                        "ldc1  $f20,0(%2);"
                        "ldc1  $f20,0(%1);"
                        "l20: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 22:{
                    ASM("sdc1  $f22,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l22;"
                        "ldc1  $f22,0(%2);"
                        "ldc1  $f22,0(%1);"
                        "l22: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 24:{
                    ASM("sdc1  $f24,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l24;"
                        "ldc1  $f24,0(%2);"
                        "ldc1  $f24,0(%1);"
                        "l24: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 26:{
                    ASM("sdc1  $f26,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l26;"
                        "ldc1  $f26,0(%2);"
                        "ldc1  $f26,0(%1);"
                        "l26: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 28:{
                    ASM("sdc1  $f28,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l28;"
                        "ldc1  $f28,0(%2);"
                        "ldc1  $f28,0(%1);"
                        "l28: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                case 30:{
                    ASM("sdc1  $f30,0(%0);"
                        "lb    t0,7(%0);"
                        "andi  t0,t0,0x80;"
                        "beq   t0,zero,l30;"
                        "ldc1  $f30,0(%2);"
                        "ldc1  $f30,0(%1);"
                        "l30: "
                        , &dividend, &ninf, &pinf);
                     break;
                }
                default:assert(0 && "in DoFpuException:this register \
                    doesn't exist! \n");
            }
            ASM(".set  reorder;");
        }
        else if (0x10 == pInsDiv->fmt){
            char pinf[]={'\x00','\x00','\x00','\x40'};
            char ninf[]={'\x00','\x00','\x00','\xc0'};
            ASM(".set  noreorder;");
            switch (pInsDiv->fs){
                case 0:{
                    ASM("mfc1   t0,$f0;"
                        "srl    t0,t0,31;"
                        "beq    t0,zero,s0;"
                        "lwc1   $f0,0(%1);"
                        "lwc1   $f0,0(%0);"
                        "s0: "
                        ,&ninf, &pinf);
                    break;
                }
                case 2:{
                    ASM("mfc1   t0,$f2;"
                        "srl    t0,t0,31;"
                        "beq    t0,zero,s2;"
                        "lwc1   $f2,0(%1);"
                        "lwc1   $f2,0(%0);"
                        "s2: "
                        ,&ninf, &pinf);
                    break;
                }
                case 4:{
                    ASM("mfc1   t0,$f4;"
                        "srl    t0,t0,31;"
                        "beq    t0,zero,s4;"
                        "lwc1   $f4,0(%1);"
                        "lwc1   $f4,0(%0);"
                        "s4: "
                        ,&ninf, &pinf);
                    break;
                }
                case 6:{
                    ASM("mfc1   t0,$f6;"
                        "srl    t0,t0,31;"
                        "beq    t0,zero,s6;"
                        "lwc1   $f6,0(%1);"
                        "lwc1   $f6,0(%0);"
                        "s6: "
                        ,&ninf, &pinf);
                    break;
                }
                case 8:{
                    ASM("mfc1   t0,$f8;"
                        "srl    t0,t0,31;"
                        "beq    t0,zero,s8;"
                        "lwc1   $f8,0(%1);"
                        "lwc1   $f8,0(%0);"
                        "s8: "
                        ,&ninf, &pinf);
                    break;
                }
                case 10:{
                    ASM("mfc1  t0,$f10;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s10;"
                        "lwc1  $f10,0(%1);"
                        "lwc1  $f10,0(%0);"
                        "s10: "
                        ,&ninf, &pinf);
                    break;
                }
                case 12:{
                    ASM("mfc1  t0,$f12;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s12;"
                        "lwc1  $f12,0(%1);"
                        "lwc1  $f12,0(%0);"
                        "s12: "
                        ,&ninf, &pinf);
                    break;
                }
                case 14:{
                    ASM("mfc1  t0,$f14;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s14;"
                        "lwc1  $f14,0(%1);"
                        "lwc1  $f14,0(%0);"
                        "s14: "
                        ,&ninf, &pinf);
                    break;
                }
                case 16:{
                    ASM("mfc1  t0,$f16;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s16;"
                        "lwc1  $f16,0(%1);"
                        "lwc1  $f16,0(%0);"
                        "s16: "
                        ,&ninf, &pinf);
                    break;
                }
                case 18:{
                    ASM("mfc1  t0,$f18;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s18;"
                        "lwc1  $f18,0(%1);"
                        "lwc1  $f18,0(%0);"
                        "s18: "
                        ,&ninf, &pinf);
                    break;
                }
                case 20:{
                    ASM("mfc1  t0,$f20;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s20;"
                        "lwc1  $f20,0(%1);"
                        "lwc1  $f20,0(%0);"
                        "s20: "
                        ,&ninf, &pinf);
                    break;
                }
                case 22:{
                    ASM("mfc1  t0,$f22;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s22;"
                        "lwc1  $f22,0(%1);"
                        "lwc1  $f22,0(%0);"
                        "s22: "
                        ,&ninf, &pinf);
                    break;
                }
                case 24:{
                    ASM("mfc1  t0,$f24;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s24;"
                        "lwc1  $f24,0(%1);"
                        "lwc1  $f24,0(%0);"
                        "s24: "
                        ,&ninf, &pinf);
                    break;
                }
                case 26:{
                    ASM("mfc1  t0,$f26;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s26;"
                        "lwc1  $f26,0(%1);"
                        "lwc1  $f26,0(%0);"
                        "s26: "
                        ,&ninf, &pinf);
                    break;
                }
                case 28:{
                    ASM("mfc1  t0,$f28;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s28;"
                        "lwc1  $f28,0(%1);"
                        "lwc1  $f28,0(%0);"
                        "s28: "
                        ,&ninf, &pinf);
                    break;
                }
                case 30:{
                    ASM("mfc1  t0,$f30;"
                        "srl   t0,t0,31;"
                        "beq   t0,zero,s30;"
                        "lwc1  $f30,0(%1);"
                        "lwc1  $f30,0(%0);"
                        "s30: "
                        ,&ninf, &pinf);
                    break;
                }
                default:assert(0 && "in DoFpuException: \
                    this register doesn't exist!! \n");
            }
            ASM(".set  reorder;");
        }
        else
            goto ERREXIT;
#else
#error no EVC compiler
#endif
    }
    else
        goto ERREXIT;

    return true;
ERREXIT:
    kprintf("it's not dividing zero exception\n");
    return false;
}
